#include <iostream>
#include <thread>
#include <mutex>
#include <map>
#include <string>
#include <functional>
#include <stdexcept>
#include "ThreadWrapper.h"
#include "ThreadPool.h"
#include <unordered_map>
/**
 * @file ThreadMangent.h
 * @brief Header file for the ThreadMangent class.
 * 
 * The ThreadMangent.h file contains the declaration of the ThreadMangent class, a utility class    
 * Example usage and further details are provided within the class documentation.
 * 
 * @author liuzhiyu (liuzhiyu27@foxmail.com)
 * @copyright Copyright (c) 2023 by liuzhiyu, All Rights Reserved.
 */
enum class ThreadAttribute
{
    ALL,
    ThreadName,
    ThreadFunc,
    ThreadRunning,
    ThreadCount,
};
enum class ThreadPriority {
    HIGHEST = -20,       // 最高优先级
    VERY_HIGH = -10,
    HIGH = -5,
    ABOVE_NORMAL = -2,
    NORMAL = 0,          // 默认优先级
    BELOW_NORMAL = 5,
    LOW = 10,
    VERY_LOW = 15,
    LOWEST = 19          // 最低优先级
};

class ThreadMangent
{   
private:
    /* data */
    ThreadPool* m_threadPool;
    mutable std::mutex m_mutex;
    std::unordered_map<std::string, std::unique_ptr<ThreadWrapper>> threadMap;
    ThreadMangent(/* args */);
    ~ThreadMangent();
#ifdef _WIN32
    /**
     * @brief Maps a Linux thread priority to a Windows thread priority.
     * @param linuxPriority The Linux thread priority to be mapped.
     * 
     * This method is used internally to map a Linux thread priority to a Windows thread priority.
     * It is used when setting the thread priority on Windows systems.
     * 
     * @return The mapped Windows thread priority.
     */
    int _MapLinuxPriorityToWindows(ThreadPriority linuxPriority)const;
#endif
    bool _addTask(std::string taskname, std::function<void()> func =  nullptr, ThreadPriority priority = ThreadPriority::NORMAL );
public: 
    static ThreadMangent& getInstance(){
        static ThreadMangent instance;
        return instance;
    }
    bool addTask(std::string taskname, ThreadPriority priority = ThreadPriority::NORMAL  );///<It is not recommended to use, and the thread function cannot be set
    bool addTask(std::string taskname, std::function<void()> func, ThreadPriority priority = ThreadPriority::NORMAL ); 

    bool addTasks(std::vector<std::pair<std::string, std::function<void()>>> tasknames, ThreadPriority priority = ThreadPriority::NORMAL);   
    bool addTasks(std::map<std::string, std::function<void()>> tasknames, ThreadPriority priority = ThreadPriority::NORMAL );  
    bool addTasks(std::vector<std::string> tasknames, ThreadPriority priority = ThreadPriority::NORMAL );
    bool setMain(std::string taskname, std::function<void()> func);

    bool start(std::string threadName, bool lock = true); 
    bool startAll();

    int getRunningThreadCount()const;
    int getThreadCount()const;
    int checkThreads(ThreadAttribute attribute = ThreadAttribute::ALL, std::string threadName = "")const;

    bool stop(std::string threadName, bool lock = true);
    bool stopAll();

    bool join(std::string threadName, bool lock = true);
    bool joinAll();


};